"""
FastAPI 主应用 - SQLAlchemy 集成完整示例

整合 SQLAlchemy 和 CRUD 操作，实现用户-文章-标签系统

运行方式：
cd /Users/baimu/PycharmProjects/fastApiProject3/stage2_advanced/chapter01_database
uvicorn main:app --reload --port 8010

访问：
- API 文档: http://127.0.0.1:8010/docs
- 根路径: http://127.0.0.1:8010/
"""

from fastapi import FastAPI, HTTPException, Depends, status
from sqlalchemy.orm import Session
from typing import List
import sys
from pathlib import Path

# 添加项目根目录到 Python 路径
if __name__ == "__main__" or "." not in __name__:
    sys.path.insert(0, str(Path(__file__).parent.parent.parent))
    import stage2_advanced.chapter01_database.crud as crud
    import stage2_advanced.chapter01_database.schemas as schemas
    import stage2_advanced.chapter01_database.models as models
    from stage2_advanced.chapter01_database.database import engine, get_db
else:
    from . import crud, schemas, models
    from .database import engine, get_db

# 创建所有表
models.Base.metadata.create_all(bind=engine)

# 创建应用
app = FastAPI(
    title="📊 第1章：数据库集成",
    description="""
    ## SQLAlchemy ORM 完整示例
    
    实现功能：
    - ✅ 用户管理（CRUD）
    - ✅ 文章管理（CRUD）
    - ✅ 标签管理（CRUD）
    - ✅ 一对多关系（用户-文章）
    - ✅ 多对多关系（文章-标签）
    
    ## 学习要点
    - SQLAlchemy 模型定义
    - 数据库会话管理
    - CRUD 操作封装
    - 表关系映射
    - FastAPI 数据库集成
    """,
    version="1.0.0",
)


# ========== 根路径 ==========

@app.get("/", tags=["系统"])
async def root():
    """系统根路径"""
    return {
        "message": "欢迎来到第1章：数据库集成！",
        "features": [
            "用户管理（CRUD）",
            "文章管理（CRUD）",
            "标签管理（CRUD）",
            "一对多关系（用户-文章）",
            "多对多关系（文章-标签）",
        ],
        "docs": "/docs",
        "examples": {
            "创建用户": "POST /users/",
            "获取用户列表": "GET /users/",
            "创建文章": "POST /users/{user_id}/posts/",
            "创建标签": "POST /tags/",
        }
    }


# ========== 用户相关接口 ==========

@app.post(
    "/users/",
    response_model=schemas.UserResponse,
    status_code=status.HTTP_201_CREATED,
    tags=["用户管理"],
    summary="创建用户",
)
def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)):
    """
    创建新用户
    
    ## 验证规则
    - 用户名：3-50 字符，唯一
    - 邮箱：有效邮箱格式，唯一
    - 密码：至少 8 字符
    
    ## 返回
    - 201：创建成功
    - 400：用户名或邮箱已存在
    """
    # 检查用户名
    db_user = crud.get_user_by_username(db, username=user.username)
    if db_user:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="用户名已存在"
        )
    
    # 检查邮箱
    db_user = crud.get_user_by_email(db, email=user.email)
    if db_user:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="邮箱已被使用"
        )
    
    return crud.create_user(db=db, user=user)


@app.get(
    "/users/",
    response_model=List[schemas.UserResponse],
    tags=["用户管理"],
    summary="获取用户列表",
)
def read_users(
    skip: int = 0,
    limit: int = 100,
    is_active: bool = None,
    db: Session = Depends(get_db),
):
    """
    获取用户列表（支持分页和筛选）
    
    ## 查询参数
    - **skip**: 跳过的记录数（分页）
    - **limit**: 返回的最大记录数（分页）
    - **is_active**: 活跃状态筛选
    """
    users = crud.get_users(db, skip=skip, limit=limit, is_active=is_active)
    return users


@app.get(
    "/users/{user_id}",
    response_model=schemas.UserResponse,
    tags=["用户管理"],
    summary="获取指定用户",
)
def read_user(user_id: int, db: Session = Depends(get_db)):
    """
    根据 ID 获取用户信息
    
    ## 返回
    - 200：成功
    - 404：用户不存在
    """
    db_user = crud.get_user(db, user_id=user_id)
    if db_user is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="用户不存在"
        )
    return db_user


@app.get(
    "/users/{user_id}/with-posts",
    response_model=schemas.UserWithPosts,
    tags=["用户管理"],
    summary="获取用户及其文章",
)
def read_user_with_posts(user_id: int, db: Session = Depends(get_db)):
    """
    获取用户及其所有文章
    
    演示一对多关系查询
    """
    db_user = crud.get_user(db, user_id=user_id)
    if db_user is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="用户不存在"
        )
    return db_user


@app.patch(
    "/users/{user_id}",
    response_model=schemas.UserResponse,
    tags=["用户管理"],
    summary="更新用户信息",
)
def update_user(
    user_id: int,
    user_update: schemas.UserUpdate,
    db: Session = Depends(get_db),
):
    """更新用户信息（部分更新）"""
    db_user = crud.update_user(db, user_id=user_id, user_update=user_update)
    if db_user is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="用户不存在"
        )
    return db_user


@app.delete(
    "/users/{user_id}",
    status_code=status.HTTP_204_NO_CONTENT,
    tags=["用户管理"],
    summary="删除用户",
)
def delete_user(user_id: int, db: Session = Depends(get_db)):
    """
    删除用户
    
    由于配置了级联删除，用户的所有文章也会被删除
    """
    success = crud.delete_user(db, user_id=user_id)
    if not success:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="用户不存在"
        )


# ========== 文章相关接口 ==========

@app.post(
    "/users/{user_id}/posts/",
    response_model=schemas.PostResponse,
    status_code=status.HTTP_201_CREATED,
    tags=["文章管理"],
    summary="创建文章",
)
def create_post(
    user_id: int,
    post: schemas.PostCreate,
    db: Session = Depends(get_db),
):
    """
    为指定用户创建文章
    
    可以同时指定文章的标签（tag_ids）
    """
    # 检查用户是否存在
    db_user = crud.get_user(db, user_id=user_id)
    if db_user is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="用户不存在"
        )
    
    return crud.create_post(db=db, post=post, author_id=user_id)


@app.get(
    "/posts/",
    response_model=List[schemas.PostResponse],
    tags=["文章管理"],
    summary="获取文章列表",
)
def read_posts(
    skip: int = 0,
    limit: int = 100,
    author_id: int = None,
    is_published: bool = None,
    db: Session = Depends(get_db),
):
    """
    获取文章列表（支持分页和筛选）
    
    ## 查询参数
    - **skip**: 跳过的记录数
    - **limit**: 返回的最大记录数
    - **author_id**: 按作者筛选
    - **is_published**: 按发布状态筛选
    """
    posts = crud.get_posts(
        db,
        skip=skip,
        limit=limit,
        author_id=author_id,
        is_published=is_published,
    )
    return posts


@app.get(
    "/posts/{post_id}",
    response_model=schemas.PostWithDetails,
    tags=["文章管理"],
    summary="获取文章详情",
)
def read_post(post_id: int, db: Session = Depends(get_db)):
    """
    获取文章详情（包含作者和标签）
    
    演示多表关联查询
    同时自动增加浏览量
    """
    db_post = crud.get_post(db, post_id=post_id)
    if db_post is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="文章不存在"
        )
    
    # 增加浏览量
    crud.increment_post_views(db, post_id=post_id)
    
    return db_post


@app.patch(
    "/posts/{post_id}",
    response_model=schemas.PostResponse,
    tags=["文章管理"],
    summary="更新文章",
)
def update_post(
    post_id: int,
    post_update: schemas.PostUpdate,
    db: Session = Depends(get_db),
):
    """更新文章（部分更新）"""
    db_post = crud.update_post(db, post_id=post_id, post_update=post_update)
    if db_post is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="文章不存在"
        )
    return db_post


@app.delete(
    "/posts/{post_id}",
    status_code=status.HTTP_204_NO_CONTENT,
    tags=["文章管理"],
    summary="删除文章",
)
def delete_post(post_id: int, db: Session = Depends(get_db)):
    """删除文章"""
    success = crud.delete_post(db, post_id=post_id)
    if not success:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="文章不存在"
        )


# ========== 标签相关接口 ==========

@app.post(
    "/tags/",
    response_model=schemas.TagResponse,
    status_code=status.HTTP_201_CREATED,
    tags=["标签管理"],
    summary="创建标签",
)
def create_tag(tag: schemas.TagCreate, db: Session = Depends(get_db)):
    """
    创建新标签
    
    标签名称必须唯一
    """
    db_tag = crud.get_tag_by_name(db, name=tag.name)
    if db_tag:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="标签名称已存在"
        )
    
    return crud.create_tag(db=db, tag=tag)


@app.get(
    "/tags/",
    response_model=List[schemas.TagResponse],
    tags=["标签管理"],
    summary="获取标签列表",
)
def read_tags(
    skip: int = 0,
    limit: int = 100,
    db: Session = Depends(get_db),
):
    """获取标签列表"""
    tags = crud.get_tags(db, skip=skip, limit=limit)
    return tags


@app.get(
    "/tags/{tag_id}",
    response_model=schemas.TagResponse,
    tags=["标签管理"],
    summary="获取标签详情",
)
def read_tag(tag_id: int, db: Session = Depends(get_db)):
    """获取标签详情"""
    db_tag = crud.get_tag(db, tag_id=tag_id)
    if db_tag is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="标签不存在"
        )
    return db_tag


@app.delete(
    "/tags/{tag_id}",
    status_code=status.HTTP_204_NO_CONTENT,
    tags=["标签管理"],
    summary="删除标签",
)
def delete_tag(tag_id: int, db: Session = Depends(get_db)):
    """删除标签"""
    success = crud.delete_tag(db, tag_id=tag_id)
    if not success:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="标签不存在"
        )


# ========== 启动事件 ==========

@app.on_event("startup")
async def startup_event():
    """应用启动时执行"""
    print("=" * 60)
    print("🚀 第1章：数据库集成 - 启动成功！")
    print("=" * 60)
    print("📚 API 文档: http://127.0.0.1:8010/docs")
    print("📖 ReDoc: http://127.0.0.1:8010/redoc")
    print("=" * 60)
    print("💡 试试这些接口:")
    print("  1. POST /users/ - 创建用户")
    print("  2. POST /users/1/posts/ - 创建文章")
    print("  3. POST /tags/ - 创建标签")
    print("  4. GET /users/1/with-posts - 查看用户及其文章")
    print("=" * 60)

